using System;
using System.Collections.Generic;
using System.ComponentModel;
using Blazing.BusinessObjects.Cms;
using Blazing.BusinessObjects.Queries;
using Iesi.Collections.Generic;
using System.BusinessObjects.With;
//using System.Web.UI;
using System.Linq;
using System.BusinessObjects.Data;
using System.Collections;
using Blazing.BusinessObjects.Tagging;
using System.Web;

namespace Blazing.WebFacade
{
    [System.ComponentModel.DataObject]
    public class PageController
    {
        #region Page
        [DataObjectMethod(DataObjectMethodType.Delete, true)]
        public Contentpage DeletePage(Contentpage page)
        {
            Contentpage.Evict(page.ID);
            Contentpage delPage = Contentpage.Load(page.ID);
            page.Delete();
            delPage.Delete();

            delPage.Save(SaveMode.Flush);

            Site.Evict(delPage.Site.ID);
            FacadeCacheManager.Invalidate<Contentpage>(page.ID);

            return page;
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Insert, true)]
        public int NewPage(Contentpage page)
        {
            if (HttpContext.Current != null)
                page.CreatedBy = HttpContext.Current.User.Identity.Name;

            page.Save(SaveMode.Flush);
            Site.Evict(page.Site.ID);
            return page.ID;
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Update, true)]
        public void UpdatePage(Contentpage page)
        {
            Contentpage.Evict(page.ID);

            if (page.MenuItems != null)
            {
                foreach (MenuItem item in page.MenuItems)
                {
                    MenuItem.Evict(item.ID);
                    item.Refresh();
                }
            }

            if (HttpContext.Current != null)
                page.ModifiedBy = HttpContext.Current.User.Identity.Name;

            page.Save(SaveMode.Flush);

            Contentpage.Evict(page.ID);
            Site.Evict(page.Site.ID);

            FacadeCacheManager.Invalidate<Contentpage>(page.ID);
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
        public ISet<Contentpage> GetPages(int siteId)
        {
            Site obj = Site.Load(siteId);
            return obj != null ? obj.Pages : null;
        }

        public IList<Contentpage> GetPages(Site site, IList<TaxonomyTag> filter, int limit)
        {
            List<Contentpage> list = new List<Contentpage>(Contentpage.Search(QrySearchPagesByTaxonomyTags.Query(filter, site).SetMaxResults(limit)));

            //reverse normal sorting order to get the newest first
            list.Sort((arg0, arg1) => arg0.CreatedDate.CompareTo(arg1.CreatedDate));

            return list;
        }

        public IList<Contentpage> GetPages(Site site, IList<TaxonomyTag> filter, bool orderByCreated, int limit)
        {
            List<Contentpage> list = new List<Contentpage>(Contentpage.Search(QrySearchPagesByTaxonomyTags.Query(filter, site, orderByCreated).SetMaxResults(limit)));

            //reverse normal sorting order to get the newest first
            list.Sort((arg0, arg1) => arg0.CreatedDate.CompareTo(arg1.CreatedDate));

            return list;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
        public List<Contentpage> GetPages(int siteId, string filter, string tags, string sortExpression)
        {
            List<Contentpage> retList = new List<Contentpage>();
            Site obj = Site.Load(siteId);

            if (obj != null && obj.Pages != null)
            {
                retList.AddRange(
                        from p in obj.Pages
                        where (string.IsNullOrEmpty(filter) ? true : p.Name.ToLower().IndexOf(filter.ToLower()) > -1)
                            && (string.IsNullOrEmpty(tags) ? true : p.TaxonomyTags.Count(taxTag => tags.IndexOf(taxTag.Tag.Name) > -1) > 0)
                        select p
                    );

                if (sortExpression != String.Empty)
                {
                    string[] sortOptions = sortExpression.Split(' ');
                    if (sortOptions.Length > 0)
                    {
                        string order = sortOptions.Length > 1 ? sortOptions[1] : "ASC";
                        GenericObjectComparer<Contentpage> comparer = new GenericObjectComparer<Contentpage>(sortOptions[0], order);
                        retList.Sort(comparer);
                    }
                }
            }
            return retList;
        }

        static object pageLoaderSync = new object();
        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public Contentpage GetPage(int pageId)
        {
            Contentpage retval = FacadeCacheManager.GetItem<Contentpage,int>(arg0 => Contentpage.Load(arg0),
                pageId, ref pageLoaderSync, pageId);
            return retval;
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public IList<Contentpage> GetPages(int siteId, Nullable<int> parentPageId)
        {
            return Contentpage.Search(QrySearchPages.Query(siteId, parentPageId));
        }

        public Contentpage GetPage(int siteId, string url, bool ?active)
        {
            Contentpage retval = null;

            Func<int> loadAction = ()=>
            {
                Contentpage page = Contentpage.Fetch(QryFetchPageByUrl.Query(siteId, url));

                if (page != null && active.HasValue && active.Value == page.IsActive)
                    return page.ID;
                return 0;
            };

            retval = FacadeCacheManager.GetItemCache<Contentpage>(loadAction,
                arg0 => GetPage(arg0), ref pageLoaderSync, siteId, url, active);

            return retval;
        }

        public Contentpage GetPage(int siteId, string url)
        {
            return GetPage(siteId, url, true);
        }
        #endregion

        #region PageTypes
        [DataObjectMethodAttribute(DataObjectMethodType.Delete)]
        public void DeletePageType(PageType page)
        {
            page.Delete();
            page.Save();
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Insert)]
        public int NewPageType(PageType page)
        {
            page.Save();
            return page.ID;
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Update)]
        public void UpdatePageType(PageType page)
        {
            page.Save();
        }

        [DataObjectMethodAttribute(DataObjectMethodType.Select)]
        public IList<PageType> GetPageTypes()
        {
            return PageType.Search(QrySearchPageTypes.Query());
        }
        #endregion

        #region PageFeedback
        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Insert)]
        public FeedbackItem InsertPageFeedback(Contentpage page, FeedbackItem item)
        {
            Contentpage.Evict(page.ID);
            page = Contentpage.Load(page.ID);

            //make sure items are loaded...seems to error otherwise
            int num = page.FeedbackItems.Count;

            item.Name = CleanUserInput(item.Name);
            item.UserName = CleanUserInput(item.UserName);
            item.Content = CleanUserInput(item.Content);
            item.CreatedDate = DateTime.Now;
            item.IsApproved = true;

            With.Transaction.Execute(()=>
            {
                item.Save();
                page.FeedbackItems.Add(item);
                page.Save();
            });

            FacadeCacheManager.Invalidate<Contentpage>(page.ID);

            return item;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select)]
        public IList<FeedbackItem> GetPageFeedbackItems(Contentpage page)
        {
            IList<FeedbackItem> retval = FeedbackItem.Search(QrySearchFeedbackItems.Query(page.ID, true));
            return retval;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select)]
        public IList<FeedbackItem> GetSiteFeedbackItems(int siteId)
        {
            IList<FeedbackItem> retval = FeedbackItem.Search(QrySearchFeedbackItems.QueryFeedbackOnSite(siteId));
            return retval;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete)]
        public FeedbackItem DeleteFeedbackItem(FeedbackItem item)
        {
            
            FeedbackItem.Evict(item.ID);
            FeedbackItem save = FeedbackItem.Load(item.ID);
            save.Delete();

            IList<Contentpage> pageLinks = Contentpage.Search(QrySearchFeedbackItems.QueryPageWithItem(item.ID));

            With.Transaction.Execute(()=>
            {
                foreach (Contentpage p in pageLinks)
                {
                    p.FeedbackItems.Remove(save);
                    p.Save();
                    FacadeCacheManager.Invalidate<Contentpage>(p.ID);
                }
                save.Save();
            });

            return save;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update)]
        public FeedbackItem UpdateFeedbackItem(FeedbackItem item)
        {
            FeedbackItem.Evict(item.ID);
            FeedbackItem save = FeedbackItem.Load(item.ID);
            save.IsApproved = item.IsApproved;
            save.Name = item.Name;
            save.UserUrl = item.UserUrl;
            save.Content = item.Content;

            With.Transaction.Execute(() => save.Save());

            return save;
        }

        public static string CleanUserInput(string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;

            string retval = input.Replace("<", "&lt;").Replace(">", "&gt;");
            return retval;
        }
        #endregion
    }
}
